//
// WorldCreation class - main class that creates the world and runs the simulator
//
package classes;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class WorldCreation {

	public static char[][][] newWorld;

	public static int[][] occupiedPlaces;
	public static int size ;
	private static int customerSize;
	
	private static int numberOfPits = 0;
	//Pit Wampus Gold Agent Bat Exit
	// 0 - pit, 1 - wampus, 2 - gold, 3 - agent, 4 - bat, 5 - exit
	
	public static int variationsFeelingsForCell = 6;
	
	public static void main(String[] args) {
		
		System.out.println("Start");
		
		customerSize = size = getSizeFromCustomer();
		
		newWorld = new char[size][size][variationsFeelingsForCell];
		occupiedPlaces = new int[size][size];
		
		generateCustomerWorld();

		World world = new World(size,newWorld);
		world.printWorld();
    world.setPerceptMap();
    
	  Agent agent = new Agent(world);

	  int i;
	  for(i =0; i < 50; i++) {
	   
	    System.out.print("Move " + i + ": ");
	    Point directionPoint = agent.nextMove();
		
      if (newWorld[world.getAgentLocation().getX()][world.getAgentLocation().getY()][2] == 'G')
        world.grabGold(world.getAgentLocation().getX(), world.getAgentLocation().getY());
    
      if (newWorld[world.getAgentLocation().getX()][world.getAgentLocation().getY()][4] == 'B')
        directionPoint = world.batsMooving();
     
		  // check what is in cell
		  char feelingOfCell = ' '; 
		  if (newWorld[directionPoint.getX()][directionPoint.getY()][0] == 'P') {
			  feelingOfCell  = 'P';
		  }
		  if (newWorld[directionPoint.getX()][directionPoint.getY()][1] == 'W') {
			  feelingOfCell  = 'W';
	  	}
		  if (newWorld[directionPoint.getX()][directionPoint.getY()][2] == 'G') {
			  feelingOfCell  = 'G';
		  }
		  if (newWorld[directionPoint.getX()][directionPoint.getY()][4] == 'B') {
			  feelingOfCell  = 'B';
		  }
		  if (newWorld[directionPoint.getX()][directionPoint.getY()][5] == 'E') {
			  feelingOfCell  = 'E';
		  }
		
		  if (feelingOfCell == 'W' || feelingOfCell == 'P') {
			  System.out.println("End of the game");
			  world.moveAgentToLocation(directionPoint);
			  world.printWorld();
        break;
		  }
		  
		  if (feelingOfCell == 'E') {
			  if(agent.isHasGold()) {
				  System.out.println("Success! Exit with gold!");
				  world.moveAgentToLocation(directionPoint);
				  world.printWorld();
				  break;
			  } else {
				  agent.knowsExitLocation = true;
				  agent.findExit(directionPoint);
				  System.out.println("Exit without gold!");
			  }
		  }
		
		  if (feelingOfCell == 'G') {
        System.out.println("Gold found!");
	    }
    
		  if (feelingOfCell == 'B') {
			  System.out.println("Bat move agent to a different location!");
		  }
		
		  if (feelingOfCell == ' ') {
			  System.out.println("Nothing");
		  }
		
		  world.moveAgentToLocation(directionPoint);
		  world.printWorld();
	  }
  
	  if (i==50) System.out.println("End of simulation / Agent didn't reach the Exit");
 	}
	
	public static void generateCustomerWorld() {
		
		// initialize empty world
		for (int i = 0; i < size; i++) {
			for (int j = 0; j < size; j++) {
				for (int k = 0; k < variationsFeelingsForCell; k++) {
					newWorld[i][j][k] = ' '; 
				}
			}
		}
		
		for (int i = 0; i < size; i++) {
			for (int j = 0; j < size; j++) {
				occupiedPlaces[i][j] = 0;
			}
		}
		
    // Agent Position
    Point customerPositionPoint = getAgentPositionFromCustomer(customerSize);
    newWorld[customerPositionPoint.getX()][customerPositionPoint.getY()][3] = 'A';
    occupiedPlaces[customerPositionPoint.getX()][customerPositionPoint.getY()] = 1;

    // Gold Position
    Point goldPositionPoint = getGoldPositionFromCustomer(customerSize);
		newWorld[goldPositionPoint.getX()][goldPositionPoint.getY()][2] = 'G';
		occupiedPlaces[goldPositionPoint.getX()][goldPositionPoint.getY()] = 1;
		
		// Pits Positions
    Point[] pitsArr = getPitsPositionFromCustomer(customerSize);
		for (int i = 0; i < pitsArr.length; i++) {
			newWorld[pitsArr[i].getX()][pitsArr[i].getY()][0] = 'P';
		}
		
		// Bats Position
    Point[] batsArr = getBatsPositionFromCustomer(customerSize);
		for (int i = 0; i < batsArr.length; i++) {
			newWorld[batsArr[i].getX()][batsArr[i].getY()][4] = 'B';
		}
		
		// Wampus Position
    Point wampusPositionPoint = getWampusPositionFromCustomer(customerSize);
		newWorld[wampusPositionPoint.getX()][wampusPositionPoint.getY()][1] = 'W';
		occupiedPlaces[wampusPositionPoint.getX()][wampusPositionPoint.getY()] = 1;
		
		// Exit Position
    Point exitsPositionPoint = getExitPositionFromCustomer(customerSize);
		newWorld[exitsPositionPoint.getX()][exitsPositionPoint.getY()][5] = 'E';
		occupiedPlaces[exitsPositionPoint.getX()][exitsPositionPoint.getY()] = 1;
	}
	
	public static int getSizeFromCustomer() {
		String input = null;
		int number = 0;
		int minWorldSize = 3;

		System.out.println("Please, put interval with which you want to make field: ");
		boolean notFoundNumber = true;
		while (notFoundNumber) {
			try {
				BufferedReader bufferedReader = new BufferedReader(
						new InputStreamReader(System.in));
				input = bufferedReader.readLine();
				number = Integer.parseInt(input);
				if (number < minWorldSize) {
					System.out
							.println("Try again. Please, put interval more than "
									+ minWorldSize + ".");
				} else {
					notFoundNumber = false;
					System.out.println("World will be created with " + number
							+ " x " + number + " size.");
					System.out.println();
				}
			} catch (NumberFormatException ex) {
				System.out.println("Not a number ! Please, type a number. ");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return number;
	}
	
	public static Point getAgentPositionFromCustomer(int customerSize) {
		String input = null;
		int xNumber = 0;
		int yNumber = 0;
		
		System.out.println("Please, specify coordinates for agent. ");
		
		boolean numberPrinted = false;
		while (numberPrinted != true) {
			try {
				System.out.println("Please, put x coordinate for agent: ");
				BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
				input = bufferedReader.readLine();
				xNumber = Integer.parseInt(input);
				if (xNumber >= 0 && xNumber < customerSize) {
					numberPrinted = true;
				}
				else {
					System.out.println("Please, put possible x.");
				}
				System.out.println();
			} catch (NumberFormatException ex) {
				System.out.println("Not a number ! Please, type a number.");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		numberPrinted = false;
		
		System.out.println("Please, put y coordinate for agent: ");
		while (numberPrinted != true) {
			try {
				BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
				input = bufferedReader.readLine();
				yNumber = Integer.parseInt(input);
				if (yNumber >= 0 && yNumber < customerSize) {
					numberPrinted = true;
				}
				else {
					System.out.println("Please, put possible y.");
				}
				System.out.println();
			} catch (NumberFormatException ex) {
				System.out.println("Not a number ! Please, type a number.");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}	
		return new Point(xNumber, yNumber);
	}
	
	public static Point getGoldPositionFromCustomer(int customerSize) {
		String input = null;
		
		boolean placeNotFound = true;
		System.out.println("Generating location for gold: ");
		int xNumber = 0;
		int yNumber = 0;
		
		while (placeNotFound) {
			xNumber = 0;
			yNumber = 0;
			
			boolean notFoundnumberPrinted = true;
			while (notFoundnumberPrinted) {
				try {
					System.out.println("Please, specify 'x' for gold position: ");
					BufferedReader bufferedReader = new BufferedReader(
							new InputStreamReader(System.in));
					input = bufferedReader.readLine();
					xNumber = Integer.parseInt(input);
					if (xNumber >= 0 && xNumber < customerSize) {
						notFoundnumberPrinted = false;
					}
					else {
						System.out.println("Please, put possible x");
					}
					System.out.println();
				} catch (NumberFormatException ex) {
					System.out
							.println("Not a number ! Please, type a number. ");
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			
			notFoundnumberPrinted = true;

			System.out.println("Please, specify 'y' for gold position: ");
			while (notFoundnumberPrinted) {
				try {
					BufferedReader bufferedReader = new BufferedReader(
							new InputStreamReader(System.in));
					input = bufferedReader.readLine();
					yNumber = Integer.parseInt(input);
					if (yNumber >= 0 && yNumber < customerSize) {
						notFoundnumberPrinted = false;
					}
					else {
						System.out.println("Please, put possible y.");
					}
					System.out.println();
				} catch (NumberFormatException ex) {
					System.out
							.println("Not a number ! Please, type a number. ");
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			if(occupiedPlaces[xNumber][yNumber] == 0) {
				placeNotFound = false;
			} 
		}
		return new Point(xNumber, yNumber);
	}
	
	public static Point[] getPitsPositionFromCustomer(int customerSize) {
		
		// need to return array of pits
		
		// get number of Pits
		String input = null;
		int minPitsNumber = 0;
		int maxPitsNumber = (customerSize * customerSize - numberOfPits - 4)/2;;
		
		boolean notFoundnumberPitsPrinted = true;
		
		while (notFoundnumberPitsPrinted) {
			System.out.println("Please, put number of pits: ");
			try {
				BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
				input = bufferedReader.readLine();
				numberOfPits = Integer.parseInt(input);
				if (numberOfPits > maxPitsNumber) {
					System.out.println("Try again. Please, put number of pits more than "
							+ minPitsNumber + ".");
				}
				else if (numberOfPits < minPitsNumber) {
					System.out.println("Try again. Please, put number of pits less than "
							+ maxPitsNumber + ".");
				}
				else if (numberOfPits <= maxPitsNumber && numberOfPits >= minPitsNumber){
					notFoundnumberPitsPrinted = false;
				}
			} catch (NumberFormatException ex) {
				System.out.println("Not a number ! Please, type a number. ");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		Point[] pitsLocations = new Point[numberOfPits];
		
		int xNumber = 0;
		int yNumber = 0;
		
		// now have number of Pits
		for (int i = 0; i < numberOfPits; i++) { 
			xNumber = 0;
			yNumber = 0;
			boolean  notFindPlace = true;
			while (notFindPlace){
				System.out.println("Generating location for pits: ");
				
					xNumber = 0;
					yNumber = 0;
					System.out.println("Please, specify 'x' for pits position: ");
					boolean notNumberPrinted = true;
					while (notNumberPrinted) {
						try {
							BufferedReader bufferedReader = new BufferedReader(
									new InputStreamReader(System.in));
							input = bufferedReader.readLine();
							xNumber = Integer.parseInt(input);
							notNumberPrinted = false;
							System.out.println();
						} catch (NumberFormatException ex) {
							System.out
									.println("Not a number ! Please, type a number. ");
						} catch (IOException e) {
							e.printStackTrace();
						}
					}

					notNumberPrinted = true;

					System.out.println("Please, specify 'y' for pits position: ");
					while (notNumberPrinted) {
						try {
							BufferedReader bufferedReader = new BufferedReader(
									new InputStreamReader(System.in));
							input = bufferedReader.readLine();
							yNumber = Integer.parseInt(input);
							notNumberPrinted = false;
							System.out.println();
						} catch (NumberFormatException ex) {
							System.out
									.println("Not a number ! Please, type a number. ");
						} catch (IOException e) {
							e.printStackTrace();
						}
					}

					if(occupiedPlaces[xNumber][yNumber] != 1) {
						notFindPlace = false;
					} 
				}
				// add to array
				occupiedPlaces[xNumber][yNumber] = 1;
				pitsLocations[i] = new Point(xNumber, yNumber);
			}

		return pitsLocations;	
	}
	
	public static Point[] getBatsPositionFromCustomer(int customerSize) {
		
		// need to return array of bats
		
		// get number of Pits
		String input = null;
		int minBatsNumber = 0;
		int maxBatsNumber = customerSize * customerSize - 4;
		int numberOfBats = 0;
		
		boolean notFoundnumberBatsPrinted = true;
		
		while (notFoundnumberBatsPrinted) {
			System.out.println("Please, put number of bats: ");
			try {
				BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
				input = bufferedReader.readLine();
				numberOfBats = Integer.parseInt(input);
				if (numberOfBats > maxBatsNumber) {
					System.out.println("Try again. Please, put number of bats more than "
							+ minBatsNumber + ".");
				}
				else if (numberOfBats < minBatsNumber) {
					System.out.println("Try again. Please, put number of bats less than "
							+ maxBatsNumber + ".");
				}
				else if (numberOfBats <= maxBatsNumber && numberOfBats >= minBatsNumber){
					notFoundnumberBatsPrinted = false;
				}
			} catch (NumberFormatException ex) {
				System.out.println("Not a number ! Please, type a number. ");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		Point[] batsLocations = new Point[numberOfBats];
		
		int xNumber = 0;
		int yNumber = 0;
		
		// now have number of Pits
		for (int i = 0; i < numberOfBats; i++) { 
			xNumber = 0;
			yNumber = 0;
			boolean  notFindPlace = true;
			while (notFindPlace){
				System.out.println("Generating location for bats: ");
				
					xNumber = 0;
					yNumber = 0;
					System.out.println("Please, specify 'x' for bats position: ");
					boolean notNumberPrinted = true;
					while (notNumberPrinted) {
						try {
							BufferedReader bufferedReader = new BufferedReader(
									new InputStreamReader(System.in));
							input = bufferedReader.readLine();
							xNumber = Integer.parseInt(input);
							notNumberPrinted = false;
							System.out.println();
						} catch (NumberFormatException ex) {
							System.out
									.println("Not a number ! Please, type a number. ");
						} catch (IOException e) {
							e.printStackTrace();
						}
					}

					notNumberPrinted = true;

					System.out.println("Please, specify 'y' for bats position: ");
					while (notNumberPrinted) {
						try {
							BufferedReader bufferedReader = new BufferedReader(
									new InputStreamReader(System.in));
							input = bufferedReader.readLine();
							yNumber = Integer.parseInt(input);
							notNumberPrinted = false;
							System.out.println();
						} catch (NumberFormatException ex) {
							System.out
									.println("Not a number ! Please, type a number. ");
						} catch (IOException e) {
							e.printStackTrace();
						}
					}

					if(occupiedPlaces[xNumber][yNumber] != 1) {
						notFindPlace = false;
					} 
					else {
						System.out
						.println("Try gain this place is occupied!");
					}
				}
				// add to array
				occupiedPlaces[xNumber][yNumber] = 1;
				batsLocations[i] = new Point(xNumber, yNumber);
			}
		return batsLocations;
	}
	
	public static Point getWampusPositionFromCustomer(int customerSize) {
		String input = null;
		
		boolean placeNotFound = true;
		System.out.println("Generating location for wampus: ");
		int xNumber = 0;
		int yNumber = 0;
		
		while (placeNotFound) {
			xNumber = 0;
			yNumber = 0;
			
			boolean notFoundnumberPrinted = true;
			while (notFoundnumberPrinted) {
				try {
					System.out.println("Please, specify 'x' for wampus position: ");
					BufferedReader bufferedReader = new BufferedReader(
							new InputStreamReader(System.in));
					input = bufferedReader.readLine();
					xNumber = Integer.parseInt(input);
					if (xNumber >= 0 && xNumber < customerSize) {
						notFoundnumberPrinted  = false;
					}
					else {
						System.out.println("Please, put possible x.");
					}
					System.out.println();
				} catch (NumberFormatException ex) {
					System.out
							.println("Not a number ! Please, type a number. ");
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			
			notFoundnumberPrinted = true;

			System.out.println("Please, specify 'y' for wampus position: ");
			while (notFoundnumberPrinted) {
				try {
					BufferedReader bufferedReader = new BufferedReader(
							new InputStreamReader(System.in));
					input = bufferedReader.readLine();
					yNumber = Integer.parseInt(input);
					if (yNumber >= 0 && yNumber < customerSize) {
						notFoundnumberPrinted = false;
					}
					else {
						System.out.println("Please, put possible y.");
					}
					System.out.println();
				} catch (NumberFormatException ex) {
					System.out
							.println("Not a number ! Please, type a number. ");
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			if(occupiedPlaces[xNumber][yNumber] == 0) {
				placeNotFound = false;
			} 
			else {
				System.out
				.println("Try gain this place is occupied!");
			}
		}
		return new Point(xNumber, yNumber);
	}

	public static Point getExitPositionFromCustomer(int customerSize) {
		String input = null;
		
		boolean placeNotFound = true;
		System.out.println("Generating location for exit: ");
		int xNumber = 0;
		int yNumber = 0;
		
		while (placeNotFound) {
			xNumber = 0;
			yNumber = 0;
			
			boolean notFoundnumberPrinted = true;
			while (notFoundnumberPrinted) {
				try {
					System.out.println("Please, specify 'x' for exit position: ");
					BufferedReader bufferedReader = new BufferedReader(
							new InputStreamReader(System.in));
					input = bufferedReader.readLine();
					xNumber = Integer.parseInt(input);
					if (xNumber >= 0 && xNumber < customerSize) {
						notFoundnumberPrinted  = false;
					}
					else {
						System.out.println("Please, put possible x.");
					}
					System.out.println();
				} catch (NumberFormatException ex) {
					System.out
							.println("Not a number ! Please, type a number. ");
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			
			notFoundnumberPrinted = true;

			System.out.println("Please, specify 'y' for exit position: ");
			while (notFoundnumberPrinted) {
				try {
					BufferedReader bufferedReader = new BufferedReader(
							new InputStreamReader(System.in));
					input = bufferedReader.readLine();
					yNumber = Integer.parseInt(input);
					if (yNumber >= 0 && yNumber < customerSize) {
						notFoundnumberPrinted = false;
					}
					else {
						System.out.println("Please, put possible y.");
					}
					System.out.println();
				} catch (NumberFormatException ex) {
					System.out
							.println("Not a number ! Please, type a number. ");
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			if(occupiedPlaces[xNumber][yNumber] == 0) {
				placeNotFound = false;
			}
			else {
				System.out
				.println("Try gain this place is occupied!");
			}
		}
		return new Point(xNumber, yNumber);
	}
}
